package cn.yilongquan.service.impl;

import cn.yilongquan.mapper.RoleMapper;
import cn.yilongquan.mapper.RoleMenuMapper;
import cn.yilongquan.mapper.RolePermissionMapper;
import cn.yilongquan.service.RoleService;
import cn.yilongquan.user.domain.Role;
import cn.yilongquan.user.domain.rolePermission;
import cn.yilongquan.user.query.RoleQuery;
import cn.yilongquan.util.CustomPageResult;
import cn.yilongquan.util.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private RolePermissionMapper RolePermissionMapper;
    @Autowired
    private RoleMenuMapper roleMenuMapper;
    @Override
    @Transactional
    public void add(Role role) {
        Role sn = roleMapper.findBySn(role.getSn());
        if (sn == null) {
            roleMapper.add(role);
            Long roleId = role.getId();
            this.saveRolePermissions(roleId, role.getPermissionIds());
        } else {
            throw new RuntimeException("角色编码已经存在");
        }
    }

    @Override
    @Transactional
    public void update(Role role) {
        Role sn = roleMapper.findBySn(role.getSn());
        if (sn != null && !sn.getId().equals(role.getId())) {
            throw new RuntimeException("角色编码已经存在");

        }
        // 1. 更新角色基本信息
        roleMapper.update(role);
        // 2. 更新角色与权限的关联关系
        this.saveRolePermissions(role.getId(), role.getPermissionIds());
        this.saveRoleMenus(role.getId(), role.getMenuIds());
    }

    @Override
    @Transactional
    public void saveRolePermissions(Long roleId, List<Long> permissionIds) {
        // 步骤1：先删除该角色原有的所有权限关联（避免旧数据残留）
        RolePermissionMapper.deleteByRoleId(roleId);

        // 步骤2：如果有新选择的权限，批量插入新的关联关系
        if (permissionIds != null && !permissionIds.isEmpty()) {
            // 构建角色-权限关联对象列表
            List<rolePermission> rolePermissions = permissionIds.stream()
                    .map(permId -> {
                        rolePermission rp = new rolePermission();
                        rp.setRoleId(roleId);
                        rp.setPermissionId(permId);
                        return rp;
                    })
                    .collect(Collectors.toList());
            // 批量插入关联关系
            RolePermissionMapper.batchInsert(rolePermissions);
        }
    }

    // 从关联表查询该角色对应的所有权限ID
    @Override
    public List<Long> getPermissionIdsByRoleId(Long roleId) {
        return roleMapper.getPermissionIdsByRoleId(roleId);
    }

    @Override
    @Transactional
    public void saveRoleMenus(Long roleId, List<Long> menuIds) {
        // 1. 删除原有关联
        roleMenuMapper.deleteByRoleId(roleId);
        // 2. 插入新关联（若 menuIds 为空则跳过）
        if (menuIds != null && !menuIds.isEmpty()) {
            roleMenuMapper.batchInsert(roleId, menuIds);
        }
    }
    // 从关联表查询该角色对应的所有权限ID
    @Override
    public List<Long> getMenuIdsByRoleId(Long roleId) {
        return roleMapper.getMenuIdsByRoleId(roleId);
    }

    @Override
    @Transactional
    public void deleteById(Long id) {
        // 这里可以添加删除前的业务校验，如检查是否有关联数据
        // 1. 校验角色是否存在
        Role existRole = roleMapper.findById(id);
        if (existRole == null) {
            throw new IllegalArgumentException("角色不存在，无法删除");
        }
        //和菜单表menu的数据关联校验
        Long countbyroleandmenu = roleMapper.countroleandmenuByroleID(id);
        Long countroleandpermissionByroleID = roleMapper.countroleandpermissionByroleID(id);

        if (countbyroleandmenu > 0 || countroleandpermissionByroleID > 0)  {
            throw new IllegalStateException("该角色已关联菜单或者权限，请先解除关联再删除");
        }
            roleMapper.deleteById(id);
    }

//批量删除
    @Override
    @Transactional
    public void batchDelete(List<Long> ids) {
        // 这里可以添加批量删除前的业务校验
        for (Long id : ids) {
            // 复用deleteById中的校验逻辑（或抽取为私有方法）
            Long countMenu = roleMapper.countroleandmenuByroleID(id);
            Long countPerm = roleMapper.countroleandpermissionByroleID(id);
            if (countMenu > 0 || countPerm > 0) {
                throw new IllegalStateException("角色ID：" + id + "已关联菜单或权限，无法批量删除");
            }
        }
        roleMapper.batchDelete(ids);
    }




    @Override
    public Role findById(Long id) {
        return roleMapper.findById(id);
    }

    @Override
    public List<Role> findAll() {
        return roleMapper.findAll();
    }

    @Override
    public R pageList(RoleQuery roleQuery) {
        // 计算偏移量
        Integer page = roleQuery.getPage();
        Integer size = roleQuery.getSize();
        roleQuery.setOffset((page - 1) * size);
        // 查询总记录数
        Long total = roleMapper.count(roleQuery);
        // 查询当前页数据
        List<Role> rows = roleMapper.pageList(roleQuery);
        // 构建分页结果
        CustomPageResult<Role> pageResult = new CustomPageResult<>(
                total,
                rows,
                page,
                size
        );

        return R.ok(pageResult);
    }


    @Override
    public boolean isRoleCodeUnique(String code, Long excludeId) {
        // 1. 边界处理：若编码为空，直接返回不唯一（或根据业务判定）
        if (code == null || code.trim().isEmpty()) {
            return false; // 编码为空不允许，视为不唯一
        }

        // 2. 直接查询数据库中“编码相同且ID不等于excludeId”的角色数量
        // 优化点：用SQL条件查询，避免全表查询和循环判断
        int count = roleMapper.countBySnAndNotId(code, excludeId);

        // 3. 若 count > 0，说明存在重复编码（被其他角色占用）
        return count == 0;

    }



}
